home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / mmv10.zip / MMV.C < prev    next >
Text File  |  1989-11-22  |  60KB  |  2,855 lines

  1. /*
  2.     mmv 1.0
  3.     Copyright (c) 1989 Vladimir Lanin.
  4.     This program may be freely used and copied on a non-commercial basis.
  5.  
  6.     Author may be reached at:
  7.  
  8.     lanin@csd2.nyu.edu
  9.  
  10.     Vladimir Lanin
  11.     330 Wadsworth Ave, Apt 6F,
  12.     New York, NY 10040
  13. */
  14.  
  15. /*
  16.     Define SYSV to compile under System V.
  17.     If your System V has a rename() call, define RENAME.
  18.     Otherwise, mmv will only be able to rename directories (via option -r)
  19.     when running as the super-user.
  20.     There is no reason to set the suid bit on mmv if rename() is available.
  21.     It is important that mmv not be run with effective uid set
  22.     to any value other than either the real uid or the super-user.
  23.     Even when running with effective uid set to super-user,
  24.     mmv will only perform actions permitted to the real uid.
  25.  
  26.     Define MSDOS to compile under MS-D*S Turbo C 1.5.
  27.     If you prefer mmv's output to use /'s instead of \'s under MS-D*S,
  28.     define SLASH.
  29.  
  30.     When neither MSDOS nor SYSV are defined, compiles under BSD.
  31.  
  32.     RENAME is automatically defined under MSDOS and BSD.
  33.  
  34.     If you are running a (UN*X) system that provides the
  35.     "struct dirent" readdir() directory reading standard,
  36.     define DIRENT. Otherwise, mmv uses the BSD-like
  37.     "struct direct" readdir().
  38.     If your (UN*X) system has neither of these, get the "dirent"
  39.     by Doug Gwyn, available as gwyn-dir-lib in volume 9
  40.     of the comp.sources.unix archives.
  41. */
  42.  
  43. static char USAGE[] =
  44. #ifdef MSDOS
  45.  
  46. "Usage: \
  47. %s [-m|x%s|c|o|a|z] [-h] [-d|p] [-g|t] [-v|n] [from to]\n\
  48. \n\
  49. Use #N in the ``to'' pattern to get the string matched\n\
  50. by the N'th ``from'' pattern wildcard.\n";
  51.  
  52. #define OTHEROPT (_osmajor < 3 ? "" : "|r")
  53.  
  54. #else
  55.  
  56. "Usage: \
  57. %s [-m|x|r|c|o|a|l%s] [-h] [-d|p] [-g|t] [-v|n] [from to]\n\
  58. \n\
  59. Use #[l|u]N in the ``to'' pattern to get the [lowercase|uppercase of the]\n\
  60. string matched by the N'th ``from'' pattern wildcard.\n\
  61. \n\
  62. A ``from'' pattern containing wildcards should be quoted when given\n\
  63. on the command line.\n";
  64.  
  65. #ifdef SYSV
  66. #define OTHEROPT ""
  67. #else
  68. #define OTHEROPT "|s"
  69. #endif
  70.  
  71. #endif
  72.  
  73. #include <stdio.h>
  74. #include <ctype.h>
  75. #include <string.h>
  76.  
  77. #ifdef MSDOS
  78. /* for MS-DOS (under Turbo C 1.5)*/
  79.  
  80. #include <stdlib.h>
  81. #include <sys/stat.h>
  82. #include <dos.h>
  83. #include <dir.h>
  84. #include <io.h>
  85. #include <fcntl.h>
  86.  
  87. #define ESC '\''
  88. #ifdef SLASH
  89. #define SLASH '\\'
  90. #define OTHERSLASH '/'
  91. #else
  92. #define SLASH '/'
  93. #define OTHERSLASH '\\'
  94. #endif
  95.  
  96. typedef int DIRID;
  97. typedef int DEVID;
  98.  
  99. static char TTY[] = "/dev/con";
  100. extern unsigned _stklen = 10000;
  101.  
  102. #define RENAME
  103.  
  104. #else
  105. /* for various flavors of UN*X */
  106.  
  107. #include <sys/types.h>
  108. #include <sys/stat.h>
  109. #include <sys/file.h>
  110. #include <sys/signal.h>
  111. #include <fcntl.h>
  112. extern char *getenv();
  113. extern long lseek();
  114. extern char *malloc();
  115.  
  116. #ifdef DIRENT
  117. #include <dirent.h>
  118. typedef struct dirent DIRENTRY;
  119. #else
  120. #ifdef SYSV
  121. #include <sys/dir.h>
  122. /* might need to be changed to <dir.h> */
  123. #else
  124. #include <sys/dir.h>
  125. #endif
  126. typedef struct direct DIRENTRY;
  127. #endif
  128.  
  129. #define void char    /* might want to remove this line */
  130.  
  131. #ifndef O_BINARY
  132. #define O_BINARY 0
  133. #endif
  134. #ifndef R_OK
  135. #define R_OK 4
  136. #define W_OK 2
  137. #define X_OK 1
  138. #endif
  139.  
  140. #define ESC '\\'
  141. #define SLASH '/'
  142.  
  143. typedef ino_t DIRID;
  144. typedef dev_t DEVID;
  145.  
  146. #define MAXPATH 1024
  147.  
  148. static char TTY[] = "/dev/tty";
  149.  
  150. #ifdef SYSV
  151. /* for System V */
  152.  
  153. struct utimbuf {
  154.     time_t actime;
  155.     time_t modtime;
  156. };
  157. #define utimes(f, t) utime((f), (t))
  158.  
  159.  
  160. #else
  161. /* for BSD */
  162.  
  163. #define RENAME
  164.  
  165. #include <sys/time.h>
  166.  
  167. #endif
  168.  
  169. #endif
  170.  
  171.  
  172. #define mylower(c) (isupper(c) ? (c)-'A'+'a' : (c))
  173. #define myupper(c) (islower(c) ? (c)-'a'+'A' : (c))
  174. #define STRLEN(s) (sizeof(s) - 1)
  175. #define mydup(s) (strcpy((char *)challoc(strlen(s) + 1, 0), (s)))
  176.  
  177.  
  178. #define DFLT 0x001
  179. #define NORMCOPY 0x002
  180. #define OVERWRITE 0x004
  181. #define NORMMOVE 0x008
  182. #define XMOVE 0x010
  183. #define DIRMOVE 0x020
  184. #define NORMAPPEND 0x040
  185. #define ZAPPEND 0x080
  186. #define HARDLINK 0x100
  187. #define SYMLINK 0x200
  188.  
  189. #define COPY (NORMCOPY | OVERWRITE)
  190. #define MOVE (NORMMOVE | XMOVE | DIRMOVE)
  191. #define APPEND (NORMAPPEND | ZAPPEND)
  192. #define LINK (HARDLINK | SYMLINK)
  193.  
  194. static char MOVENAME[] = "mmv";
  195. static char COPYNAME[] = "mcp";
  196. static char APPENDNAME[] = "mad";
  197. static char LINKNAME[] = "mln";
  198.  
  199. #define ASKDEL 0
  200. #define ALLDEL 1
  201. #define NODEL 2
  202.  
  203. #define ASKBAD 0
  204. #define SKIPBAD 1
  205. #define ABORTBAD 2
  206.  
  207. #define STAY 0
  208. #define LOWER 1
  209. #define UPPER 2
  210.  
  211. #define MAXWILD 20
  212. #define MAXPATLEN MAXPATH
  213. #define INITROOM 10
  214. #define CHUNKSIZE 2048
  215. #define BUFSIZE 4096
  216.  
  217. #define FI_STTAKEN 0x01
  218. #define FI_LINKERR 0x02
  219. #define FI_INSTICKY 0x04
  220. #define FI_NODEL 0x08
  221. #define FI_KNOWWRITE 0x010
  222. #define FI_CANWRITE 0x20
  223. #define FI_ISDIR 0x40
  224. #define FI_ISLNK 0x80
  225.  
  226. typedef struct {
  227.     char *fi_name;
  228.     struct rep *fi_rep;
  229. #ifdef MSDOS
  230.     char fi_attrib;
  231. #else
  232.     short fi_mode;
  233.     char fi_stflags;
  234. #endif
  235. } FILEINFO;
  236.  
  237. #define DI_KNOWWRITE 0x01
  238. #define DI_CANWRITE 0x02
  239. #define DI_CLEANED 0x04
  240.  
  241. typedef struct {
  242.     DEVID di_vid;
  243.     DIRID di_did;
  244.     unsigned di_nfils;
  245.     FILEINFO **di_fils;
  246.     char di_flags;
  247. } DIRINFO;
  248.  
  249. #define H_NODIR 1
  250. #define H_NOREADDIR 2
  251.  
  252. typedef struct {
  253.     char *h_name;
  254.     DIRINFO *h_di;
  255.     char h_err;
  256. } HANDLE;
  257.  
  258. #define R_ISX 0x01
  259. #define R_SKIP 0x02
  260. #define R_DELOK 0x04
  261. #define R_ISALIASED 0x08
  262. #define R_ISCYCLE 0x10
  263. #define R_ONEDIRLINK 0x20
  264.  
  265. typedef struct rep {
  266.     HANDLE *r_hfrom;
  267.     FILEINFO *r_ffrom;
  268.     HANDLE *r_hto;
  269.     char *r_nto;            /* non-path part of new name */
  270.     FILEINFO *r_fdel;
  271.     struct rep *r_first;
  272.     struct rep *r_thendo;
  273.     struct rep *r_next;
  274.     char r_flags;
  275. } REP;
  276.  
  277. typedef struct {
  278.     REP *rd_p;
  279.     DIRINFO *rd_dto;
  280.     char *rd_nto;
  281.     unsigned rd_i;
  282. } REPDICT;
  283.  
  284. typedef struct chunk {
  285.     struct chunk *ch_next;
  286.     unsigned ch_len;
  287. } CHUNK;
  288.  
  289. typedef struct {
  290.     CHUNK *sl_first;
  291.     char *sl_unused;
  292.     int sl_len;
  293. } SLICER;
  294.  
  295.  
  296. static void init(/* */);
  297. static void procargs(/* int argc, char **argv,
  298.     char **pfrompat, char **ptopat */);
  299. static void matchpats(/* char *cfrom, char *cto */);
  300. static int getpat(/* */);
  301. static int getword(/* char *buf */);
  302. static void matchpat(/*  */);
  303. static int parsepat(/*  */);
  304. static int dostage(/* char *lastend, char *pathend,
  305.     char **start1, int *len1, int stage, int anylev */);
  306. static int trymatch(/* FILEINFO *ffrom, char *pat */);
  307. static int keepmatch(/* FILEINFO *ffrom, char *pathend,
  308.     int *pk, int needslash, int dirs, int fils */);
  309. static int badrep(/* HANDLE *hfrom, FILEINFO *ffrom,
  310.     HANDLE **phto, char **pnto, FILEINFO **pfdel, int *pflags */);
  311. static int checkto(/* HANDLE *hfrom, char *f,
  312.     HANDLE **phto, char **pnto, FILEINFO **pfdel */);
  313. static char *getpath(/* char *tpath */);
  314. static int badname(/* char *s */);
  315. static FILEINFO *fsearch(/* char *s, DIRINFO *d */);
  316. static int ffirst(/* char *s, int n, DIRINFO *d */);
  317. static HANDLE *checkdir(/* char *p, char *pathend, int which */);
  318. static void takedir(/*
  319.     char *p, DIRINFO *di, int sticky
  320. or
  321.     struct ffblk *pff, DIRINFO *di
  322. */);
  323. static int fcmp(/* FILEINFO **pf1, FILEINFO **pf2 */);
  324. static HANDLE *hadd(/* char *n */);
  325. static int hsearch(/* char *n, int which, HANDLE **ph */);
  326. static DIRINFO *dadd(/* DEVID v, DIRID d */);
  327. static DIRINFO *dsearch(/* DEVID v, DIRID d */);
  328. static int match(/* char *pat, char *s, char **start1, int *len1 */);
  329. static void makerep(/*  */);
  330. static void checkcollisions(/*  */);
  331. static int rdcmp(/* REPDICT *rd1, REPDICT *rd2 */);
  332. static void findorder(/*  */);
  333. static void scandeletes(/* int (*pkilldel)(REP *p) */);
  334. static int baddel(/* REP *p */);
  335. static int skipdel(/* REP *p */);
  336. static void nochains(/*  */);
  337. static void printchain(/* REP *p */);
  338. static void goonordie(/*  */);
  339. static void doreps(/*  */);
  340. static long appendalias(/* REP *first, REP *p, int *pprintaliased */);
  341. static int movealias(/* REP *first, REP *p, int *pprintaliased */);
  342. static int snap(/* REP *first, REP *p */);
  343. static void showdone(/* REP *fin */);
  344. static void breakout(/*  */);
  345. static int breakrep(/* */);
  346. static void breakstat(/* */);
  347. static void quit(/*  */);
  348. static int copymove(/* REP *p */);
  349. static int copy(/* FI